package com.mandroid.forecast.util;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.mandroid.forecast.business.Weather;

public class XmlParser {
	
//	private static final SimpleDateFormat DD_MMM_YYYY = new SimpleDateFormat("dd MMM yyyy");
	
	public static String handleGeoPlanet(InputStream is){
		
		String woeid = null;
		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
		try {
			SAXParser parser = parserFactory.newSAXParser();
			GeoPlanetHandler geoPlanetHandler = new GeoPlanetHandler();
			parser.parse(is, geoPlanetHandler);
			woeid = geoPlanetHandler.woeid;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return woeid;
	}
	
	public static Weather handleWeather(InputStream is) {
		SAXParserFactory parserFactory = SAXParserFactory.newInstance();
		Weather weather = null;
		try {
			SAXParser parser = parserFactory.newSAXParser();
			WeatherHandler weatherHandler = new WeatherHandler();
			parser.parse(is, weatherHandler);
			weather = weatherHandler.weather;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if(!validate(weather)) {
			weather = null;
		}
		return weather;
	}
	
	private static class WeatherHandler extends DefaultHandler {
		
		private Weather weather;

		private int count = 0;
		
		@Override
		public void startDocument() throws SAXException {
			weather = new Weather();
		}

		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {
			String local = null;
			String value = null;
			if (WeatherLabelConstants.LOCATION.equalsIgnoreCase(localName)) {
				for ( int i = 0 ; i < attributes.getLength(); i++) {
					local = attributes.getLocalName(i);
					value = attributes.getValue(i);
					if (WeatherLabelConstants.CITY.equals(local)) {
						weather.setCity(value);
					}
					if (WeatherLabelConstants.REGION.equals(local)) {
						weather.setRegion(value);
					}
					if (WeatherLabelConstants.COUNTRY.equals(local)) {
						weather.setCountry(value);
					}					
				}
			}
			if (WeatherLabelConstants.UNITS.equalsIgnoreCase(localName)) {
				for ( int i = 0 ; i < attributes.getLength(); i++) {
					local = attributes.getLocalName(i);
					value = attributes.getValue(i);
					if (WeatherLabelConstants.TEMPERATURE.equals(local)) {
						weather.setTemperatureUnit(value);
					}
					if (WeatherLabelConstants.DISTANCE.equals(local)) {
						weather.setDistanceUnit(value);
					}
					if (WeatherLabelConstants.PRESSURE.equals(local)) {
						weather.setPressureUnit(value);
					}
					if (WeatherLabelConstants.SPEED.equals(local)) {
						weather.setSpeedUnit(value);
					}					
				}				
			}
			if (WeatherLabelConstants.ATOMSPHERE.equalsIgnoreCase(localName)) {
				for ( int i = 0 ; i < attributes.getLength(); i++) {
					local = attributes.getLocalName(i);
					value = attributes.getValue(i);
					if (WeatherLabelConstants.HUMIDITY.equals(local)) {
						weather.setHumidity(value);
					}
					if (WeatherLabelConstants.VISIBILITY.equals(local)) {
						weather.setVisibility(value);
					}
					if (WeatherLabelConstants.PRESSURE.equals(local)) {
						weather.setPressure(value);
					}				
				}				
			}
			if (WeatherLabelConstants.ASTRONOMY.equalsIgnoreCase(localName)) {
				for ( int i = 0 ; i < attributes.getLength(); i++) {
					local = attributes.getLocalName(i);
					value = attributes.getValue(i);
					if (WeatherLabelConstants.SUNRISE.equals(local)) {
						weather.setSunrise(value);
					}
					if (WeatherLabelConstants.SUNSET.equals(local)) {
						weather.setSunset(value);
					}			
				}					
			}
			if (WeatherLabelConstants.FORECAST.equalsIgnoreCase(localName)) {
				count ++;
				for ( int i = 0 ; i < attributes.getLength(); i++) {
					local = attributes.getLocalName(i);
					value = attributes.getValue(i);
					if (WeatherLabelConstants.DAY.equals(local)) {
						if(count == 1){
							weather.setDay(value);
						} else {
							weather.setForecastDay(value);
						}
					}
					if(WeatherLabelConstants.DATE.equals(local)){
						if (count == 1) {
							weather.setDate(value);
						} else {
							weather.setForecastDate(value);
						}
					}
					if (WeatherLabelConstants.TEXT.equals(local)) {
						if (count == 1) {
							weather.setText(value);
						} else {
							weather.setForecastText(value);
						}
					}
					if (WeatherLabelConstants.CODE.equals(local)) {
						if (count == 1) {
							weather.setCode(value);
						} else {
							weather.setForecastCode(value);
						}
					}
					if (WeatherLabelConstants.HIGH.equals(local)) {
						if (count == 1) {
							weather.setHigh(value);
						} else {
							weather.setForecastHigh(value);
						}
					}
					if (WeatherLabelConstants.LOW.equals(local)) {
						if (count == 1) {
							weather.setLow(value);
						} else {
							weather.setForecastLow(value);
						}
					}
				}
			}
		}
		
	}
	
	
	private static class GeoPlanetHandler extends DefaultHandler {

		
		private static final String WOEID="woeid";

		private String woeidLabel;
		
		private String woeid;
		
		@Override
		public void characters(char[] ch, int start, int length)
				throws SAXException {
			String data = new String(ch, start, length);
			if (WOEID.equals(woeidLabel)) {
				woeid = data;
			}
		}

		@Override
		public void startElement(String uri, String localName,
				String qName, Attributes attributes)
				throws SAXException {
			woeidLabel = localName;
		}
	
	}
	
	private static boolean validate(Weather weather) {
		if (weather == null || Utils.isNullOrEmpty(weather.getCode())) {
			return false;
		}
		int code = Integer.valueOf(weather.getCode());
		if (code > 47 ) {
			return false;
		}
		return true;
	}
	
}
